package com.ruoyi.mall.api.controller;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.request.BaseWxPayRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.ruoyi.common.config.XytpVoteConfig;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.mall.domain.OrderInfo;
import com.ruoyi.mall.service.OrderInfoService;
import com.ruoyi.mall.util.OrderNoCreate;
import com.ruoyi.weixin.config.CommonConstants;
import com.ruoyi.weixin.config.WxPayConfiguration;
import com.ruoyi.weixin.constant.MyReturnCode;
import com.ruoyi.weixin.utils.LocalDateTimeUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Objects;
import java.util.Optional;

/**
 * @author 立勤
 * @date 2023/07/21 11:50:43
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/api/mall/order")
@Slf4j
public class ApiOrderInfoController {

    private final OrderInfoService orderInfoService;
    private final XytpVoteConfig xytpVoteConfig;


    /**
     * 调用统一下单接口，并组装生成支付所需参数对象.
     *
     * @param orderInfo 统一下单请求参数
     * @return 返回 {@link com.github.binarywang.wxpay.bean.order}包下的类对象
     */
    @PostMapping("/unifiedOrder")
    public R<Object> unifiedOrder(@RequestBody OrderInfo orderInfo) throws WxPayException {
        orderInfo = orderInfoService.getById(orderInfo.getId());
        if(orderInfo == null){
            return R.fail(MyReturnCode.ERR_70005.getCode(), MyReturnCode.ERR_70005.getMsg());
        }
        if(!CommonConstants.NO.equals(orderInfo.getIsPay())){//只有未支付的详单能发起支付
            return R.fail(MyReturnCode.ERR_70004.getCode(), MyReturnCode.ERR_70004.getMsg());
        }
        if(orderInfo.getPaymentPrice().compareTo(BigDecimal.ZERO)==0){//0元购买不调支付
            orderInfo.setPaymentTime(LocalDateTime.now());
            orderInfoService.notifyOrder(orderInfo);
            return R.ok();
        }
        // 设置回调地址
        String notifyUrl = Optional.ofNullable(orderInfo.getNotifyUrl()).orElse("/api/mall/order/notify-order");
        WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = new WxPayUnifiedOrderRequest();
//        wxPayUnifiedOrderRequest.setAppid(appId);
        String body = orderInfo.getName();
        body = body.length() > 40 ? body.substring(0,39) : body;
        wxPayUnifiedOrderRequest.setBody(body);
        wxPayUnifiedOrderRequest.setTradeType("JSAPI");
        wxPayUnifiedOrderRequest.setNotifyUrl(xytpVoteConfig.getMall().getNotifyHost()+notifyUrl);
        wxPayUnifiedOrderRequest.setOutTradeNo(OrderNoCreate.randomOrderCode());
        wxPayUnifiedOrderRequest.setTotalFee(BaseWxPayRequest.yuanToFen(String.valueOf(orderInfo.getPaymentPrice())));
        wxPayUnifiedOrderRequest.setSpbillCreateIp("127.0.0.1");
        wxPayUnifiedOrderRequest.setOpenid(LoginHelper.getLoginUser().getOpenid());
        wxPayUnifiedOrderRequest.setTimeStart(DateUtils.dateTimeNow());     // 订单开始时间
        log.info("预支付请求参数: {}",wxPayUnifiedOrderRequest);
        WxPayService wxPayService = WxPayConfiguration.getPayService();
        return R.ok(JSONUtil.parse(wxPayService.createOrder(wxPayUnifiedOrderRequest)));
    }

    /**
     * 支付回调
     * @param xmlData
     * @return
     * @throws WxPayException
     */
    @PostMapping("/notify-order")
    public String notifyOrder(@RequestBody String xmlData) throws WxPayException {
        log.info("支付回调:"+xmlData);
        WxPayService wxPayService = WxPayConfiguration.getPayService();
        WxPayOrderNotifyResult notifyResult = wxPayService.parseOrderNotifyResult(xmlData);
        OrderInfo orderInfo = orderInfoService.getOne(Wrappers.<OrderInfo>lambdaQuery()
            .eq(OrderInfo::getOrderNo,notifyResult.getOutTradeNo()));
        if(orderInfo != null){
            if(Objects.equals(BaseWxPayRequest.yuanToFen(String.valueOf(orderInfo.getPaymentPrice())), notifyResult.getTotalFee())){
                String timeEnd = notifyResult.getTimeEnd();
                LocalDateTime paymentTime = LocalDateTimeUtils.parse(timeEnd);
                orderInfo.setPaymentTime(paymentTime);
                orderInfo.setTransactionId(notifyResult.getTransactionId());
                orderInfoService.notifyOrder(orderInfo);
                return WxPayNotifyResponse.success("成功");
            }else{
                return WxPayNotifyResponse.fail("付款金额与订单金额不等");
            }
        }else{
            return WxPayNotifyResponse.fail("无此订单");
        }
    }
}
